<template>
  <div>
    <m-shelf title="账户资料" >
      <div slot="content">
        <div class="avatar-box">
          <div class="img-box">
            <el-avatar v-if="userInfo.avatar" shape="square" :size="80" :src="'http://127.0.0.1:8000/' + userInfo.avatar"> 
              </el-avatar>
              <el-avatar v-else shape="square" :size="80" src='https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'></el-avatar>
          </div>
          <div class="r-box">
            <h3 style="margin-left: 13px;">修改头像</h3>
            <el-button type="primary" size="medium" @click="onEditAvatarShow">上传头像</el-button>
          </div>
        </div>
        <div class="content-box">
          <div class="info-box">
            <h3 class="tital">
              <span>用</span>
              <span>户</span>
              <span>ID</span>
            </h3>
            <h3 style="margin-left: 20px">{{ userInfo.username}}</h3> 
          </div>
        </div>
        <el-form :model="userInfo" ref="infoFormRef" :rules="infoFormRules">
          <div class="content-box">
            <template v-if="nicknameVisible">
              <div class="info-box">
                <h3 class="tital">用户昵称</h3> 
                <h3 style="margin-left: 20px">{{ userInfo.nickname}}</h3> 
              </div>
              <div class="r-box">
                <el-button type="primary" icon="el-icon-edit" circle @click="isShow('nicknameVisible')"></el-button>
              </div>
            </template>
            <template v-else>
              <el-form-item prop="nickname">
                <el-input ref="nicknameVisible" v-model.trim="userInfo.nickname" @blur="submit('nicknameVisible', '昵称')"></el-input>
              </el-form-item>
            </template>
          </div>
          <div class="content-box">
            <template v-if="phoneVisible">
              <div class="info-box">
                <h3 class="tital"><span>手</span><span>机</span></h3> 
                <h3 style="margin-left: 20px">{{ userInfo.phone}}</h3> 
              </div>
              <div class="r-box">
                <el-button type="primary" icon="el-icon-edit" circle @click="isShow('phoneVisible')"></el-button>
              </div>
            </template>
            <template v-else>
              <el-form-item prop="phone">
                <el-input ref="phoneVisible" v-model.trim="userInfo.phone" @blur="submit('phoneVisible', '手机号')"></el-input>
              </el-form-item>
            </template>
          </div>
          <div class="content-box">
            <template v-if="emailVisible">
              <div class="info-box">
                <h3 class="tital"><span>邮</span><span>箱</span></h3> 
                <h3 style="margin-left: 20px">{{ userInfo.email}}</h3> 
              </div>
              <div class="r-box">
                <el-button type="primary" icon="el-icon-edit" circle @click="isShow('emailVisible')"></el-button>
              </div>
            </template>
            <template v-else>
              <el-form-item prop="email">
                <el-input ref="emailVisible" v-model.trim="userInfo.email" @blur="submit('emailVisible', '邮箱')"></el-input>
              </el-form-item>
            </template>
          </div>
        </el-form>
        <div class="content-box">
          <div class="info-box">
            <h3 class="tital"><span>密</span><span>码</span></h3>
          </div>
          <div class="r-box">
            <el-button type="primary" icon="el-icon-edit" circle @click="changePassDialogVisible = true"></el-button>
          </div>
        </div>
        <el-dialog class="edit-avatar" title="修改头像" :visible.sync="editAvatarShow" width="700px" top	="30px" :modal="false">
          <div class="content">
              <div class="edit-l">
                <div style="width: 100px;height: 100px;border: 1px solid #ccc;margin-bottom: 20px;overflow: hidden;">
                  <div class="show-preview"
                        :style="{'width': previews.w + 'px','height': previews.h + 'px','overflow': 'hidden','zoom':option.zoom}">
                    <div :style="previews.div">
                      <img :src="option.img"
                            :style="previews.img"
                      >
                    </div>
                  </div>
                </div>
                <div style="padding: 10px 0 ">头像预览</div>
                <el-upload 
                  name="file"
                  ref="avatarUpload"
                  :action="uploadURL"
                  list-type="picture"
                  :show-file-list="false"
                  :auto-upload="false"
                  :on-change="handleChange"
                  :http-request="uploadAvatar">
                  <el-button size="small" type="primary" >点击上传</el-button>
                </el-upload>
              </div>
              <div class="edit-r">
                <div>
                  <div class="big" id="cropper-target" v-if="option.img">
                    <vueCropper
                      :img="option.img"
                      @realTime="realTime"
                      ref="cropper"
                      :outputSize="example2.size"
                      :info="example2.info"
                      :canScale="example2.canScale"
                      :autoCrop="example2.autoCrop"
                      :autoCropWidth="example2.width"
                      :autoCropHeight="example2.height"
                      :fixed="example2.fixed"
                    ></vueCropper>
                  </div>
                </div>
              </div>
            </div>
            <div slot="footer" class="dialog-footer">
              <el-button @click="editAvatarShow = false">取 消</el-button>
              <el-button type="primary" @click="upload">确 定</el-button>
            </div>
        </el-dialog>

        <el-dialog title="修改密码" :visible.sync="changePassDialogVisible" width="546px" @close="changePassDialogCLosed">
          <el-form :model="changePassForm" :rules="changePassRules" ref="changePassForm">
            <el-form-item prop="password">
              <el-input placeholder="原密码" type="password" v-model.trim="changePassForm.password"></el-input>
            </el-form-item>
            <el-form-item prop="newPassword">
              <el-input placeholder="新密码" type="password" v-model.trim="changePassForm.newPassword"></el-input>
            </el-form-item>
            <el-form-item prop="rePassword">
              <el-input placeholder="重复密码" type="password" v-model.trim="changePassForm.rePassword"></el-input>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer">
            <el-button @click="changePassDialogVisible = false">取 消</el-button>
            <el-button type="primary" @click="changePass()">确 定</el-button>
          </span>
        </el-dialog>
      </div>
    </m-shelf>
  </div>
</template>
<script>
import MShelf from '../../../components/shelf.vue'
import { VueCropper } from 'vue-cropper'

import { mapState, mapMutations } from 'vuex'
import { uploadAvatar, updateInfo, changePassword } from '../../../api/user'

export default {
  name: 'Information',
  data() {
    // 验证手机号码的规则
    var checkMobile = (rule, value, cb) => {
      const regMobile = /^(0|86|17951)?(13[0-9]|15[0123456789]|17[678]|18[0-9]|14[57])[0-9]{8}$/

      if (regMobile.test(value)) {
        return cb()
      }

      cb(new Error('请输入合法的手机号'))
    }
    var validatePass2 = (rule, value, callback) => {
      if (value === '') {
        callback(new Error('请再次输入密码'));
      } else if (value !== this.changePassForm.newPassword) {
        callback(new Error('两次输入密码不一致!'));
      } else {
        callback();
      }
    };
    var validateInput = (rule, value, callback) => {
      if (!this.checkSpecialKey(value)) {
        callback(new Error("不能含有特殊字符"));
      } else {
        callback();
      }
    };
    return {
      // 用户昵称，另外写一个变量是因为双绑，在修改昵称的时候，左边的信息也会变
      nickname: '',
      // 上传图片的ULRL地址
      uploadURL: '',
      // 设置File方法生成的文件的name
      imgName: '',
      // 编辑后的图片文件
      imgSrc: null,
      // 后台传回来的文件名字
      avatarname: '',
      editAvatarShow: false,
      previews: {},
      option: {
        img: '',
        zoom: 0
      },
      // vueCropper的参数
      example2: {
        info: true,
        size: 1,
        canScale: false,
        autoCrop: true,
        // 只有自动截图开启 宽度高度才生效
        autoCropWidth: 300,
        autoCropHeight: 250,
        // 开启宽度和高度比例
        fixed: true
      },
      // 控制用户信息输入框显示/隐藏
      nicknameVisible: true,
      phoneVisible: true,
      emailVisible: true,
      // 修改用户信息表单验证规则
      infoFormRules: {
        nickname: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: ['blur', 'change'] },
          { validator: validateInput, trigger: 'blur' },
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] },
          { validator: validateInput, trigger: 'blur' },
        ],
        phone: [
          { required: true, message: '请输入手机号码', trigger: 'blur' },
          { validator: checkMobile, trigger: 'blur' },
        ]
      },
      // 修改密码表单
      changePassForm: {
        password: null,
        newPassword: null,
        rePassword: null
      },
      // 控制修改密码对话框的显示/隐藏
      changePassDialogVisible: false,
      // 修改密码表单验证规则
      changePassRules: {
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur' },
          { validator: validateInput, trigger: 'blur' },
        ],
        rePassword: [
          { validator: validatePass2, trigger: 'blur' },
        ],
        newPassword: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 12, message: '长度在 6 到 12 个字符', trigger: 'blur' },
          { validator: validateInput, trigger: 'blur' },
        ],
      },
    }
  },
  computed: {
    ...mapState(['userInfo']),
  },
  methods: {
    ...mapMutations(['ISLOGIN']),
    // 选取文件前的格式验证
    handleChange(file, filelist) {
      if(filelist.length > 1) {
        filelist.shift()
      }
      const isJPG = /\.(jpg|jpeg|png|JPG|PNG)$/.test(file.raw.name)
      const isLt2M = file.size / 1024 / 1024 < 3;

      if (!isJPG) {
        return this.$notify.error({
          title: '警告',
          message: '图片类型仅支持.jpeg,jpg,png'
        })
      }
      if (!isLt2M) {
        return this.$notify.error({
          title: '警告',
          message: '上传头像图片大小不能超过 3MB!'
        })
      }

      this.option.img = file.url
      this.imgName = file.name
      return isJPG && isLt2M;
    },
    // 监听上传事件
    async uploadAvatar(file) {
      let fileObj = this.imgSrc
      let fd = new FormData()
      fd.append('file', fileObj)
      const { data: res } = await uploadAvatar(fd)
      
      if(res.code !== 0) {
        return this.$notify.error({
          title: '警告',
          message: '头像上传失败'
        })
      }
      this.avatarname = res.result.avatar
    },
    upload() {
      if (this.option.img) {
        this.$refs.cropper.getCropData((data) => {
          
          this.imgSrc = this.base64ToImg(data, this.imgName)
          this.$refs.avatarUpload.submit()

          setTimeout(async () => {
            const { data: res } = await updateInfo(this.userInfo.id, { avatar: this.avatarname, username: this.userInfo.username })

            if (res.code !== 0) {
              return this.$notify.error({
                title: '警告',
                message: '头像上传失败'
              })
            }
            // console.log(res)
            this.ISLOGIN(res.result.userInfo)
            window.sessionStorage.setItem('token', res.result.token)
            window.sessionStorage.setItem('userInfo', JSON.stringify(res.result.userInfo))
            
          }, 500)
          
          this.editAvatarShow = false
        })
      } else {
        return this.$notify.error({
          title: '警告',
          message: '请选择新头像'
        })
      }
    },
    realTime (data) {
      this.previews = data
      let w = 100 / data.w
      this.option.zoom = w
    },
    onEditAvatarShow() {
      this.editAvatarShow = true
      this.option.img = `http://127.0.0.1:8000/${this.userInfo.avatar}`
    },

    // 控制用户信息的显示/隐藏
    isShow(visible) {
      this[visible] = false
      this.$nextTick(() => {
        this.$refs[visible].focus()
      })
    },
    // 文本框失去焦点后提交信息
    async submit(visible, type) {
      this.$refs.infoFormRef.validate(async valid => {
        const confirmResult = await this.$confirm(`确认修改${type}？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).catch(err => err)

        // 如果用户确认修改，则返回字符串 confirm,取消则是 cancel
        if (confirmResult !== 'confirm') {
          this.$refs.infoFormRef.resetFields()
          return this[visible] = true
        }

        if (!valid) {
          return this.$notify.error({
            title: '警告',
            message: '验证不通过'
          })
        }

        const { data: res } = await updateInfo(this.userInfo.id, this.userInfo)

        if(res.code === 10008) {
          this.$refs[visible].focus()
          return this.$notify.error({
            title: '警告',
            message: '邮箱或手机已被绑定'
          })
        }else if(res.code !== 0) {
          this.$refs[visible].focus()
          return this.$notify.error({
            title: '警告',
            message: '信息更新失败'
          })
        }

        this.ISLOGIN(res.result.userInfo)
        window.sessionStorage.setItem('token', res.result.token)
        window.sessionStorage.setItem('userInfo', JSON.stringify(res.result.userInfo))

        this[visible] = true
        this.$router.go(0)
      })
    },
    // 监听修改密码对话框的关闭事件
    changePassDialogCLosed() {
      this.$refs.changePassForm.resetFields()
    },
    // 修改密码
    async changePass() {
      this.$refs.changePassForm.validate(async valid => {
        if (!valid) {
          return this.$message.error('验证不通过')
        }

        const confirmResult = await this.$confirm('确认修改密码?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'error'
        }).catch(err => err)

        // 如果用户确认修改，则返回字符串 confirm,取消则是 cancel
        if (confirmResult !== 'confirm') {
          return 
        }
        
        const { data: res } = await changePassword(this.userInfo.id, this.changePassForm)

        if(res.code === 10006) {
          return this.$notify.error({
            title: '警告',
            message: '原密码输入错误'
          })
        }else if (res.code !== 0) {
          return this.$notify.error({
            title: '警告',
            message: '修改密码失败'
          })
        }

        this.$notify.success({
          title: '成功',
          message: '修改密码成功，请重新登录'
        })
        this.changePassDialogVisible = false
        this.$router.push('/login')
        window.sessionStorage.clear()
      })
    },
    // base64格式转为图片文件类型
    base64ToImg(urlData, fileName) {
      let arr = urlData.split(',');
      let mime = arr[0].match(/:(.*?);/)[1];
      let bytes = window.atob(arr[1]); // 解码base64
      
      let n = bytes.length
      let ia = new Uint8Array(n);
      while (n--) {
          ia[n] = bytes.charCodeAt(n);
      }
      return new File([ia], fileName, { type: mime })
    },
    checkSpecialKey(str) {
      let specialKey = "[`~!#$^&*()=|{}':;'\\[\\]<>/?~！#￥……&*（）——|{}【】‘；：”“'。，、？]‘'";
      for (let i = 0; i < str.length; i++) {
        if (specialKey.indexOf(str.substr(i, 1)) != -1) {
          return false;
        }
      }
      return true;
    }
  },
  components: {
    MShelf,
    VueCropper
  }
}
</script>

<style lang="scss" scoped>
@import "../../../assets/style/mixin";

.el-form{
  .el-input{
    width: 928px;
    margin-top: 21px;
  }
}

.el-dialog{
  .el-form{
    .el-input{
      width: 100%;
      margin-top: -10px;
    }
  }
}

.avatar-box {
  height: 124px;
  display: flex;
  margin: 0 30px 0px;
  border-bottom: #dadada solid 1px;
  line-height: 30px;
  display: flex;
  align-items: center;
  .img-box {
    margin-top: 20px;
    width: 80px;
    border-radius: 5px;
    overflow: hidden;
  }
  .r-box {
    margin-left: 20px;
    h3 {
      font-size: 18px;
      font-weight: 400;
      color: #333;
    }
  }
}

.content-box {
  height: 80px;
  display: flex;
  margin: 0 30px 0px;
  border-bottom: #dadada solid 1px;
  line-height: 30px;
  display: flex;
  align-items: center;
  &:hover {
    .r-box {
      display: block;
    }
  }
  &:nth-of-type(6) {
    margin: 0 30px 30px;
  }
  .info-box {
    display: flex;
    width: 300px;
    margin-left: 5px;
    border-radius: 5px;
    overflow: hidden;
    .tital {
      display: flex;
      width: 76px;
      justify-content: space-between;
    }
  }
  .r-box {
    margin-left: 570px;
    display: none;
  }
  h3 {
    font-size: 19px;
    font-weight: 400;
    color: #333;
  }
}

// 修改头像
.edit-avatar {
  z-index: 9999;
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  @include wh(100%);
  background-color: rgba(0, 0, 0, .5);
  @extend %block-center;
  .content {
    display: flex;
    margin-left: 100px;
    margin-bottom: 50px;
  }
  > div {
    box-sizing: content-box;
    @include wh(700px, 500px);
    margin: 0;
  }
  input[type=file] {
    position: absolute;
    right: 0;
    left: 0;
    top: 0;
    opacity: 0;
    width: 80px;
    height: 30px;
    cursor: pointer;
    box-sizing: border-box;
    border: 15px solid #000;
    overflow: hidden;
  }
  .edit-l {
    width: 100px;
    text-align: center;
  }
  .edit-r {
    margin-left: 20px;
    flex: 1;
    > div {
      border: 1px solid #ccc;
      width: 320px;
      height: 320px;
    }
  }
}

.image-container {
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
}

.big {
  display: block;
  width: 320px;
  height: 320px;
}

.dialog-footer {
  border-top: 1px solid #E6E6E6;
  padding-top: 10px;
  margin-bottom: -10px;
}
</style>
